home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / misc_lib / config.c next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  9.4 KB  |  287 lines

  1. /*****************************************************************************
  2. *   General routines to    configuration file reading:                 *
  3. * The config file (same name as program, type .cfg) must have th following   *
  4. * format: one variable setup per line, each line consists of two params.     *
  5. * The first is variable name, which is text string without white spaces.     *
  6. * The second param. contains its value, which might be boolean (TRUE/FALSE), *
  7. * integer, or real type.                             *
  8. *   The main routine should get a structure consists of 3 elements per         *
  9. * variable: the string to match, the variable to save the data read from     *
  10. * config file, and the type (Boolean, Integer, Real), for type checking.     *
  11. * See config.h for exact definition of this data structure.             *
  12. *                                         *
  13. * Version 0.2 - adding String Type.                         *
  14. *                                         *
  15. * Written by:  Gershon Elber                   Ver 0.2, Jan. 1989    *
  16. *****************************************************************************/
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "irit_sm.h"
  21. #include "config.h"
  22. #include "imalloc.h"
  23.  
  24. /* #define    DEBUG1   Uncomment it for simple test case (see config.bat). */
  25.  
  26. #define TAB    9
  27.  
  28. /* Some fatal errors that cause this module to die... */
  29. #define    ERR_ONLY_NAME        1
  30. #define    ERR_BOOL_EXPECTED    2
  31. #define    ERR_INT_EXPECTED    3
  32. #define    ERR_REAL_EXPECTED    4
  33. #define    ERR_STRING_EXPECTED    5
  34. #define    ERR_NOT_EXISTS        6
  35.  
  36. static char *ConfigPath;
  37.  
  38. static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
  39.                              int LineCount);
  40. static void PrintConfigError(int ErrorNum, int LineCount);
  41. static FILE *FindFile(char *PrgmName, char *FileName);
  42.  
  43. /*****************************************************************************
  44. * Routine to print the current configuration data structure contents.         *
  45. *****************************************************************************/
  46. void ConfigPrint(ConfigStruct *SetUp, int NumVar)
  47. {
  48.     int i;
  49.  
  50.     fprintf(stderr, "\nCurrent defaults:\n\n");
  51.  
  52.     for (i = 0; i < NumVar; i++)
  53.         switch (SetUp[i].VarType) {
  54.         case SU_BOOLEAN_TYPE:
  55.         if (* ((int *) SetUp[i].VarData))
  56.             fprintf(stderr, "\t%-20s = TRUE\n", SetUp[i].VarName);
  57.         else
  58.             fprintf(stderr, "\t%-20s = FALSE\n", SetUp[i].VarName);
  59.         break;
  60.         case SU_INTEGER_TYPE:
  61.         fprintf(stderr, "\t%-20s = %d\n", SetUp[i].VarName,
  62.                     * ((int *) SetUp[i].VarData));
  63.         break;
  64.         case SU_REAL_TYPE:
  65. #ifdef DOUBLE
  66.         fprintf(stderr, "\t%-20s = %lg\n", SetUp[i].VarName,
  67. #else
  68.         fprintf(stderr, "\t%-20s = %g\n", SetUp[i].VarName,
  69. #endif /* DOUBLE */
  70.                     * ((RealType *) SetUp[i].VarData));
  71.         break;
  72.         case SU_STRING_TYPE:
  73.         fprintf(stderr, "\t%-20s = \"%s\"\n", SetUp[i].VarName,
  74.                     * ((char **) SetUp[i].VarData));
  75.         break;
  76.     }
  77. }
  78.  
  79. /*****************************************************************************
  80. * Main routine of config module. Gets the program name (it updates the type) *
  81. * PrgmName, and the structure defines the acceptable variables Setup.         *
  82. *****************************************************************************/
  83. void Config(char *PrgmName, ConfigStruct *SetUp, int NumVar)
  84. {
  85.     int i, LineCount = 0;
  86.     char CfgName[PATH_NAME_LEN], Line[LINE_LEN_LONG], *Cptr;
  87.     FILE *f;
  88.  
  89.     i = strlen(PrgmName) - 1;             /* Skip the full path name: */
  90.     while (i && PrgmName[i] != '\\' && PrgmName[i] != '/'
  91.           && PrgmName[i] != ':') i--;
  92.     if (i)
  93.     i++;
  94.  
  95.     strcpy(CfgName, &PrgmName[i]);
  96.     Cptr = strchr(CfgName, '.');
  97.     if (Cptr != NULL)
  98.     *Cptr = 0;                     /* Delete old type. */
  99.     strcat(CfgName, ".cfg");            /* And add the config file type. */
  100.     if ((f = FindFile(PrgmName, CfgName)) == NULL)
  101.     return;                         /* Search via path var. */
  102.  
  103.     while (!feof(f)) {
  104.     fgets(Line, LINE_LEN_LONG, f);
  105.     LineCount++;
  106.  
  107.     i = 0;    /* Delete all the part after the ; (The comment) if was any. */
  108.     while (Line[i] != 0 && Line[i] != ';') i++;
  109.         if (Line[i])
  110.         Line[i] = 0;
  111.  
  112.     i = 0;               /* Now test if that line is empty or not: */
  113.     while (Line[i] != 0 && Line[i] <= ' ') i++;    /* Skip white spaces. */
  114.  
  115.     if (Line[i])
  116.         UpdateVariable(Line, SetUp, NumVar, LineCount);
  117.     }
  118.  
  119.     fclose(f);
  120. }
  121.  
  122. /*****************************************************************************
  123. *   Routine to interpret the input Line and update the appropriate variable  *
  124. * in SetUp data structure. NumVar holds number of entries in SetUp Table.    *
  125. *****************************************************************************/
  126. static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
  127.                              int LineCount)
  128. {
  129.     int i, j;
  130.     char VarName[LINE_LEN_LONG], VarData[LINE_LEN_LONG], *StrStart, *StrEnd,
  131.     *NewStr;
  132.     RealType Dummy;      /* Force linking of floating point scanf routines. */
  133.  
  134.     i = j = 0;
  135.     while (Line[i] > ' ') {              /* Copy the Variable name: */
  136.     VarName[i] = Line[i];
  137.     i++;
  138.     }
  139.     VarName[i] = 0;
  140.  
  141.     while (Line[i] != 0 && Line[i] <= ' ') i++;
  142.     if (Line[i] == 0)
  143.     PrintConfigError(ERR_ONLY_NAME, LineCount);
  144.  
  145.     while (Line[i] >= ' ' || Line[i] == TAB)      /* Copy the Variable data: */
  146.     VarData[j++] = Line[i++];
  147.     VarData[j] = 0;
  148.  
  149.     for (i = 0; i < NumVar; i++)
  150.     if (strcmp(VarName, SetUp[i].VarName) == 0)
  151.         switch (SetUp[i].VarType) {
  152.             case SU_BOOLEAN_TYPE:
  153.             if (strnicmp(VarData, "True", 4) == 0 ||
  154.             strnicmp(VarData, "False", 5) == 0)
  155.                 *((int *) SetUp[i].VarData) =
  156.                 (strnicmp (VarData, "True", 4) == 0);
  157.             else
  158.                 PrintConfigError(ERR_BOOL_EXPECTED, LineCount);
  159.             return;
  160.         case SU_INTEGER_TYPE:
  161.             if (sscanf(VarData, "%d", (int *) SetUp[i].VarData) != 1)
  162.                 PrintConfigError(ERR_INT_EXPECTED, LineCount);
  163.             return;
  164.         case SU_REAL_TYPE:
  165. #ifdef DOUBLE
  166.             if (sscanf(VarData, "%lf", &Dummy) != 1) {
  167. #else
  168.             if (sscanf(VarData, "%f", &Dummy) != 1) {
  169. #endif /* DOUBLE */
  170.             PrintConfigError(ERR_REAL_EXPECTED, LineCount);
  171.             return;
  172.             }
  173.             *((RealType *) SetUp[i].VarData) = Dummy;
  174.             return;
  175.         case SU_STRING_TYPE:
  176.             if ((StrStart = strchr(VarData, '"')) != NULL &&
  177.             (StrEnd = strrchr(VarData, '"')) != NULL &&
  178.             StrEnd != StrStart) {
  179.             NewStr = IritMalloc(1 + ((unsigned int)
  180.                             (StrEnd - StrStart)));
  181.             j = 0;
  182.             while (++StrStart != StrEnd)
  183.                 NewStr[j++] = *StrStart;
  184.             NewStr[j] = 0;
  185.             *((char **) SetUp[i].VarData) = NewStr;
  186.             }
  187.             else
  188.             PrintConfigError(ERR_STRING_EXPECTED, LineCount);
  189.             return;
  190.        }
  191.  
  192.     PrintConfigError(ERR_NOT_EXISTS, LineCount);
  193. }
  194.  
  195. /*****************************************************************************
  196. *   Routine to print fatal configuration file error, and die.             *
  197. *****************************************************************************/
  198. static void PrintConfigError(int ErrorNum, int LineCount)
  199. {
  200.     fprintf(stderr, "Config. file error [%s line %d]: ",
  201.                         ConfigPath, LineCount);
  202.  
  203.     switch (ErrorNum) {
  204.     case ERR_ONLY_NAME:
  205.         fprintf(stderr, "Only Name found.\n");
  206.         break;
  207.         case ERR_BOOL_EXPECTED:
  208.         fprintf(stderr, "Boolean type expected.\n");
  209.         break;
  210.     case ERR_INT_EXPECTED:
  211.         fprintf(stderr, "Integer type expected.\n");
  212.         break;
  213.     case ERR_REAL_EXPECTED:
  214.         fprintf(stderr, "Real type expected.\n");
  215.         break;
  216.     case ERR_STRING_EXPECTED:
  217.         fprintf(stderr, "String (within \") type expected.\n");
  218.         break;
  219.     case ERR_NOT_EXISTS:
  220.         fprintf(stderr, "No such set up option.\n");
  221.         break;
  222.     }
  223.  
  224.     exit('c');
  225. }
  226.  
  227. /*****************************************************************************
  228. *   Routine to search for a file and open it according to attribute at all   *
  229. * directories defined by PATH environment variable and current dir.         *
  230. *****************************************************************************/
  231. static FILE *FindFile(char *PrgmName, char *FileName)
  232. {
  233.     FILE *f;
  234.  
  235.     ConfigPath = searchpath(FileName);
  236.     if ((f = fopen(ConfigPath, "rt")) != NULL)
  237.     return f;
  238.  
  239.     fprintf(stderr, "%s: Warning: No config. file (%s) found.\n",
  240.         PrgmName, FileName);
  241.  
  242.     return NULL;
  243. }
  244.  
  245. #ifdef DEBUG1
  246.  
  247. /*****************************************************************************
  248. *   Simple test routine. use it with cnfgtest.bat which rename the program   *
  249. * name so that this module will recognize the appropriate configuration file *
  250. * The arguments below assume double or non MSDOS system!.             *
  251. *****************************************************************************/
  252. void main(int argc, char **argv)
  253. {
  254.     static int Test1, Test2, Test3, Test4;
  255.     static double Test5, Test6;
  256.     static char *Test7, *Test8;
  257.  
  258.     ConfigStruct SetUp[] =
  259.     { { "TestOne",   (VoidPtr) &Test1, SU_BOOLEAN_TYPE },
  260.       { "TestTwo",   (VoidPtr) &Test2, SU_BOOLEAN_TYPE },
  261.       { "Test333",   (VoidPtr) &Test3, SU_INTEGER_TYPE },
  262.       { "Testing4",  (VoidPtr) &Test4, SU_INTEGER_TYPE },
  263.       { "TestReal5", (VoidPtr) &Test5, SU_REAL_TYPE },
  264.       { "TestReal6", (VoidPtr) &Test6, SU_REAL_TYPE },
  265.       { "String7",     (VoidPtr) &Test7, SU_STRING_TYPE },
  266.       { "String8",   (VoidPtr) &Test8, SU_STRING_TYPE } };
  267.  
  268.     Test1 = Test2 = Test3 = Test4 = 9999;
  269.     Test5 = Test6 = 0.9999;
  270.     Test7 = Test8 = NULL;
  271.  
  272.     printf("Before:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  273.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  274.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  275.  
  276.     Config(*argv, SetUp, 8); /* Do it! */
  277.  
  278.     printf("After:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  279.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  280.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  281.  
  282.     printf("\nConfigPrint prints:\n");
  283.     ConfigPrint(SetUp, 8);
  284. }
  285.  
  286. #endif /* DEBUG1 */
  287.